package com.mijie.homi.service.user;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.mijie.core.ApplicationProperties;
import com.mijie.homi.common.constant.HomiConstants;
import com.mijie.homi.common.constant.MCKey;
import com.mijie.homi.common.domain.SearchResult;
import com.mijie.homi.common.domain.user.DeviceInfo;
import com.mijie.homi.common.domain.user.Privacy;
import com.mijie.homi.common.domain.user.User;
import com.mijie.homi.common.domain.user.UserExtInfo;
import com.mijie.homi.common.util.HomiUtil;
import com.mijie.homi.dao.user.UserDao;
import com.mijie.homi.domain.user.IDBox;
import com.mijie.homi.listener.IntegrationHandler;
import com.mijie.homi.service.cache.MemcacheService;
import com.mijie.homi.service.common.MixService;
import com.mijie.homi.service.common.StatService;
import com.mijie.homi.service.message.SystemMessageService;
import com.mijie.homi.service.notify.NotifyUserAgent;
import com.mijie.homi.util.ServerHelper;
import com.mijie.util.Helper;
import com.mijie.util.HttpUtil;

@Service
public class UserService {

	@Autowired
	private UserDao dao;
	@Autowired
	private UserExtInfoService extInfoService;
	@Autowired
	private SettingService settingService;
	@Autowired
	private PrivacyService privacyService;
	@Autowired
	private IntegrationHandler integrationHandler;
	@Autowired
	private MixService mixService;
	@Autowired
	private DeviceInfoService deviceInfoService;
	@Autowired
	private IDBoxService idBoxService;
	@Autowired
	private MemcacheService mcs;
	@Autowired
	private NotifyUserAgent notifyUserAgent;
	@Autowired
	private FriendService friendService;
	@Autowired
	private StatService statService;
	@Autowired
	private SystemMessageService systemMessageService;
	
	private Logger logger = Logger.getLogger(UserService.class);
	
	public void sendMailForResetPassword(User user){
		final StringBuilder msg = new StringBuilder();
		final String code = Helper.genUUID();
		String url = ServerHelper.API_IP+"/sys/password/reset.shtml?code="+code;
		msg.append("亲爱的 ").append(user.getNickName()).append("（哈米号").append(user.getId()).append(")<br />");
		msg.append("欢迎使用重置密码功能；请点击以下链接重置您的密码（链接48小时内有效）：");
		msg.append("<a href=\""+url+"\">点击这里重置您的密码</a><br />");
		msg.append("（如果上面的链接无法直接点击，可以将以下链接复制到浏览器地址栏进行密码重置）<br />");
		msg.append(url+"<br />");
		msg.append("如果您错误的收到此邮件，可以不处理该邮件。此为系统邮件，无需回复。<br />");
		msg.append("感谢您注册哈米移动应用，祝：身体健康，幸福快乐！<br />");
		msg.append("<font color=\"gray\">");
		msg.append("----------------------------------------------------------------------------------<br />");
		msg.append("<font color=\"gray\">哈米--让您做回真正的自己<br />");
		msg.append("哈米是通过您的心情以及所分享的心情事迹映射出现实社会中各种客观存在的问题，并通过客观存在的社会现实问题和心情呈现出社会上各种各样的人物，进而通过人物的聚合和客观存在的问题帮您折射出自己内心世界的活动情况以及尽可能地帮您缓解心理上的压力甚至找到问题的解决办法。<br />");
		msg.append("</font>");
		mixService.resetPasswordApply(user.getId(), code);
		final String email = user.getEmail();
		try{
			new Thread(){
				public void run(){
					ServerHelper.sendMail(email, "哈米账号重置密码", msg.toString()) ;
				}
			}.start();
		}catch(Exception e){
			logger.error(e.getMessage(), e);
		}
	}

	
	
	public void sendMailForVerify(User user){
		if(user.getEmail().isEmpty()) return;
		
		final int id = user.getId();
		final String email = user.getEmail();
		final StringBuilder msg = new StringBuilder();
		final String code = Helper.genUUID()+"."+user.getId();
		String url = ServerHelper.API_IP+"/sys/email/verify.shtml?code="+code;
		msg.append("亲爱的 ").append(user.getNickName()).append("（哈号").append(id).append(")<br />");
		msg.append("您好！为了您的账号安全，方便您忘记密码时通过邮件找回密码，请您点击以下链接验证您的邮箱地址（48小时内有效）：");
		msg.append(url + "<br />");
		msg.append("<font size=\"-1\" color=\"gray\">（(如果您无法点击上述链接，请将它复制到浏览器地址栏后访问)）</font><br />");
		msg.append("若您错误地收到此邮件，请忽略它。哈米祝您生活愉快！<br />");
		
		try{
			new Thread(){
				public void run(){
					mixService.emailVerifyApply(id, email, code);
					ServerHelper.sendMail(email, "哈米邮箱地址验证", msg.toString()) ;
				}
			}.start();
		}catch(Exception e){
			logger.error(e.getMessage(), e);
		}
	}
	
	@Transactional(rollbackFor={Exception.class})
	public int emailVerifyPass(int id,String code){
		int rows =  dao.emailVerifyPass(id);
		if(rows>0){
			mcs.delete(MCKey.USER_BY_ID, String.valueOf(id));
			mixService.deleteEmailVerifyApply(code);
			integrationHandler.emailVerifySuccess(id);
		}
		return rows;
	}
	
	public JSONObject makeSubscribeMessage(int userId){
		User user = getUserById(userId);
		UserExtInfo userExtInfo = extInfoService.getUserExtInfoByUserId(userId);
		if(user==null || userExtInfo==null) return null;
		JSONObject content = new JSONObject();
		content.accumulate("friendId", user.getId());
		content.accumulate("nickName", user.getNickName());
		content.accumulate("avatar", HomiUtil.getRealUrl(user.getAvatar()));
		content.accumulate("mood",userExtInfo.getMood());
		content.accumulate("moodUpdateAt", userExtInfo.getMoodUpdateAt()==null?0:userExtInfo.getMoodUpdateAt().getTime());
		return content;
	}
	
	public User getUserById(int id){
		User user = (User) mcs.get(MCKey.USER_BY_ID, String.valueOf(id));
		if(user==null){
			user = dao.getUserById(id);
			if(user!=null) mcs.set(MCKey.USER_BY_ID, String.valueOf(id), MCKey.USER_CACHE_TIMEOUT, user);
		}
		return  user;
	}
	
	
	@Transactional(rollbackFor={Exception.class})
	public int register(Integer channel,Integer thirdPartType,User user,UserExtInfo info,DeviceInfo deviceInfo) throws Exception{
		IDBox idBox = idBoxService.getFreeId();
		if(idBox!=null){
			idBoxService.removeIDBox(idBox);
			user.setId(idBox.getId());
			if(user.getEmailVerified()==null)
				user.setEmailVerified(0);
			
			user.setPasswd(Helper.base64decode(user.getPasswd()));
			if(user.getAvatar()==null || user.getAvatar().trim().isEmpty()){
				user.setAvatar(ApplicationProperties.get("avatar.small.home")+"default_"+(new Random().nextInt(9)+1)+".jpg");
			}
			user.setCreateAt(new Date());
			
			info.setLocationUpdateAt(user.getCreateAt());
			info.setLastLoginAt(user.getCreateAt());
			info.setCreateAt(user.getCreateAt());
			
			
			if(!deviceInfo.getOs().equalsIgnoreCase("ios") && !deviceInfo.getOs().equalsIgnoreCase("android")){
				if(deviceInfo.getPhoneModel().startsWith("iPhone") || deviceInfo.getPhoneModel().startsWith("iPad")){
					deviceInfo.setOs("ios");
				}else{
					deviceInfo.setOs("android");
				}
			}
			
			if(deviceInfo.getOs().equalsIgnoreCase("ios")){
				//ios的terminalId和deviceId传的是一样的值
				if(deviceInfo.getDeviceId().equals("deviceTokenError")){
					deviceInfo.setDeviceId(null);
					info.setDeviceId("");
				}
			}else{
				//android只传了terminalId,而deviceId没有传
				if(info.getTerminalId().trim().isEmpty()){
					deviceInfo.setDeviceId(null);
					info.setDeviceId("");
				}else{
					deviceInfo.setDeviceId(info.getTerminalId());
				}
			}
			
				
			deviceInfo.setCreateAt(user.getCreateAt());
			
			if(dao.register(user)>0){
				sendMailForVerify(user);
				deviceInfo.setRecentUser(user.getId());
				info.setId(user.getId());
				//新注册用户不接收以往系统消息
				int maxSysMsgId = systemMessageService.getMaxSysMsgId();
				info.setSystemMsgMark(maxSysMsgId);
				
				extInfoService.createUserExtInfo(info);
				settingService.addSetting(user.getId());
				String p = String.valueOf(HomiConstants.PRIVACY_ACCESSIBLE_STRANGER);
				Privacy privacy = new Privacy();
				privacy.setId(user.getId());
				privacy.setMoodLocusVisible(p);
				privacyService.addPrivacy(privacy);
				
				
				if(channel!=null){
					DeviceInfo device = deviceInfoService.getDeviceInfo(deviceInfo.getDeviceId());
					if(device==null){
						if(thirdPartType==null){
							statService.finishSignup(channel, deviceInfo.getDeviceId());
						}else if(thirdPartType==1){
							statService.finishSignupUsingSinaWeibo(channel, deviceInfo.getDeviceId());
						}else if(thirdPartType==2){
							statService.finishSignupUsingQQWeibo(channel, deviceInfo.getDeviceId());
						}
					}
				}
				
				if(deviceInfo.getDeviceId()!=null && !deviceInfo.getDeviceId().trim().isEmpty())
					deviceInfoService.addOrUpdateDeviceInfo(deviceInfo);
				
				addUserIndex(user.getId(), user.getNickName());
			}else{
				user.setId(0);
			}
		}
		return user.getId();
	}
	
	private void addUserIndex(int userId,String nickName){
		StringBuilder url = new StringBuilder();
		url.append(ApplicationProperties.get("search.url"))
		.append("/user/index.shtml?userId=").append(userId)
		.append("&nickName=").append(nickName);
		try {
			HttpUtil.request(url.toString(), "GET".intern(), "UTF-8".intern(), null);
		} catch (IOException e) {
			logger.error(e.getMessage(), e);
		}
	}
	
	//产生马甲
	public int createInternalUser(List<User> list){
		return dao.createInternalUser(list);
	}
	
	
	public int settingAvatar(int id,String avatar){
		int rows =  dao.settingAvatar(id, avatar);
		if(rows>0){
			mcs.delete(MCKey.USER_BY_ID, String.valueOf(id));
			integrationHandler.settingVartar(id);
			notifyUserAgent.sendNotifyToSubscribers(id);
		}
		return rows;
	}
	
	
	@Transactional(rollbackFor={Exception.class})
	public int settingPasswd(int id,String passwd){
		int rows =  dao.settingPasswd(id, passwd);
		if(rows>0){
			mcs.delete(MCKey.USER_BY_ID, String.valueOf(id));
		}
		return rows;
	}
	
	@Transactional(rollbackFor={Exception.class})
	public int resetPasswdByWeb(int id,String passwd,String code){
		int rows = settingPasswd(id,Helper.MD5(passwd));
		mixService.deleteResetPasswordApply(code);//链接只使用一次
		return rows;
	}
	
	@Transactional(rollbackFor={Exception.class})
	public int update(User user){
		int rows =  dao.update(user);
		if(rows>0)
			mcs.delete(MCKey.USER_BY_ID, String.valueOf(user.getId()));
		return rows;
	}
	
	/**
	 *该方法不开放到接口，只给内部使用 
	 */
	public int updateGender(int id,int gender) throws Exception{
		int rows =  dao.updateGender(id, gender);
		if(rows>0){
			mcs.delete(MCKey.USER_BY_ID, String.valueOf(id));
			mcs.delete(MCKey.USER_EXTINFO_BY_ID, String.valueOf(id));
		}
		return rows;
	}
	
	public int updateRegion(int id,String nation,String province,String city,String district){
		int rows =  dao.updateRegion(id, nation, province, city, district);
		if(rows>0){
			mcs.delete(MCKey.USER_BY_ID, String.valueOf(id));
			integrationHandler.settingRegion(id);
		}
		return rows;
	}
	
	public int updateName(int id,String name){
		int rows = dao.updateName(id, name);
		if(rows>0){
			User user = this.getUserById(id);
			user.setName(name);
			mcs.set(MCKey.USER_BY_ID, String.valueOf(id), MCKey.USER_CACHE_TIMEOUT, user);
			integrationHandler.settinName(id);
		}
		return rows;
	}
	
	public int updateNickName(int id,String nickName){
		int rows = dao.updateNickName(id, nickName);
		if(rows>0){
			User user = this.getUserById(id);
			user.setNickName(nickName);
			mcs.set(MCKey.USER_BY_ID, String.valueOf(id), MCKey.USER_CACHE_TIMEOUT, user);
			notifyUserAgent.sendNotifyToSubscribers(id);
			addUserIndex(id, nickName);
		}
		return rows;
	}
	
	public User getUserByEmail(String email){
		return dao.getUserByEmail(email);
	}
	
	public List<User> listUserByIds(int[] ids){
		return dao.listUserByIds(ids);
	}
	
	
	public List<Integer> listInternalUser(){
		return dao.listInternalUser();
	}
	
	public List<Integer> listUserInfoSubcribers(int userId){
		return dao.listUserInfoSubcribers(userId);
	}
	
	public int addUserInfoSubcribe(int subscriber,int targetId){
		return dao.addUserInfoSubcribe(subscriber, targetId);
	}
	
	public int deleteUserInfoSubcribe(int subscriber,int targetId){
		return dao.deleteUserInfoSubcribe(subscriber,targetId);
	}
	
	
	public JSONArray searchUser(String idxf,String keyword,int offset,int limit) throws Exception {
		StringBuilder url = new StringBuilder();
		url.append(ApplicationProperties.get("search.url"))
		.append("/user/search.shtml?idxf=").append(idxf)
		.append("&keyword=").append(keyword)
		.append("&offset=").append(offset)
		.append("&limit=").append(limit);
		SearchResult result = ServerHelper.searchForList(url.toString()); 
		return result.getResult();
	}
	
	public JSONArray matchUser(String idxf,int offset,int limit,int userId,int gender) throws Exception {
		StringBuilder url = new StringBuilder();
		url.append(ApplicationProperties.get("search.url"))
		.append("/user/match.shtml?idxf=").append(idxf)
		.append("&offset=").append(offset)
		.append("&limit=").append(limit)
		.append("&userId=").append(userId)
		.append("&gender=").append(gender);
		SearchResult result = ServerHelper.searchForList(url.toString()); 
		return result.getResult();
	}
	
	public int updateEmailByUserId(String email, int userId){
		Map<String, Object> param = new HashMap<String, Object>();
		param.put("email", email);
		param.put("userId", userId);
		int rows = dao.updateEmailByUserId(param);
		if(rows > 0)
			mcs.delete(MCKey.USER_BY_ID, String.valueOf(userId));
		
		User user = getUserById(userId);
		sendMailForVerify(user);
		return rows;
	}
}
